﻿using ComponentFactory.Krypton.Toolkit;
using StableDiffusionTools.Framework;
using StableDiffusionTools.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace StableDiffusionTools
{
    public class MainApplicationContext : ApplicationContext
    {
        private CompositionContainer _container;
#pragma warning disable IDE0040 //Ignore "is never assigned to"
        [ImportMany]
        IEnumerable<Lazy<IForm, IFormData>> forms;
#pragma warning restore IDE0040 //Ignore "is never assigned to"

        List<FormEntry> initializedForms = new List<FormEntry>();
        NotifyIcon notifyIcon;

        public MainApplicationContext()
        {
            try
            {
                // An aggregate catalog that combines multiple catalogs.
                var catalog = new AggregateCatalog();
                //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
                string assemblyLocation = typeof(Program).Assembly.Location;
                if (!string.IsNullOrEmpty(assemblyLocation))
                {
                    //string extensionFolder = Path.Combine(Path.GetDirectoryName(assemblyLocation), "Extensions");
                    string assemblyFolder = Path.GetDirectoryName(assemblyLocation);
                    if (ExtendedPathInfo.GetPathInfo(assemblyFolder) == PathInfo.Directory)
                    {
                        catalog.Catalogs.Add(new DirectoryCatalog(assemblyFolder, "*.exe"));
                        //catalog.Catalogs.Add(new ApplicationCatalog());
                    }
                }
                // Create the CompositionContainer with the parts in the catalog.
                _container = new CompositionContainer(catalog);
                try
                {
                    _container.ComposeParts(this);
                }
                catch (Exception ex)
                {
                    if (ex is System.Reflection.ReflectionTypeLoadException)
                    {
                        var typeLoadException = ex as ReflectionTypeLoadException;
                        var loaderExceptions = typeLoadException.LoaderExceptions;
                    }
                    throw;
                }
            }
            catch (CompositionException ex) { /*Ignored*/ }

            ResourceManager myManager = new ResourceManager("StableDiffusionTools.Properties.Resources", GetType().Assembly);

            List<ToolStripItem> items = new List<ToolStripItem>();
            foreach (var form in forms)
            {
                Image image = null;
                if (!string.IsNullOrEmpty(form.Metadata.Image))
                {
                    image = myManager.GetObject(form.Metadata.Image) as Bitmap;
                }

                items.Add(new ToolStripMenuItem(form.Metadata.Name, image,
                    (s, e) =>
                    {
                        for (int i = 0; i < initializedForms.Count; i++)
                        {
                            if (initializedForms[i].MatchesName(((ToolStripMenuItem)s).Text)){
                                Form f = initializedForms[i].GetForm();
                                f.ShowOrActivate();
                                break;
                            }
                        }
                    }));

                initializedForms.Add(new FormEntry(form.Value, form.Metadata));
            }
            ToolStripMenuItem exitMenuItem = new ToolStripMenuItem("Exit", Properties.Resources.exit16, (s, e) => Exit());
            items.Add(exitMenuItem);

            ContextMenuStrip contextMenu = new ContextMenuStrip
            {
                ShowCheckMargin = false,
                ShowImageMargin = true
            };
            contextMenu.Items.AddRange(items.ToArray());

            notifyIcon = new NotifyIcon
            {
                Icon = ImageUtil.BitmapToIcon(Properties.Resources.toolbox),
                Text = "StableDiffusionTools",
                ContextMenuStrip = contextMenu,
                Visible = true
            };

            ThreadExit += exitThread;
        }

        private void exitThread(object sender, EventArgs e)
        {
            notifyIcon.Visible = false;
        }

        private void Exit()
        {
            bool busy = false;
            for (int i = 0; i < initializedForms.Count; i++)
            {
                if (initializedForms[i].IsBusy())
                {
                    busy = true;
                    break;
                }
            }

            if (busy)
            {
                KryptonMessageBox.Show("Closing during a running process could cause corruption", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            bool closed = true;
            for (int i = 0; i < initializedForms.Count; i++)
            {
                if (!initializedForms[i].Close())
                {
                    closed = false;
                }
            }

            if (closed)
            {
                ExitThread();
            }
        }
    }
}
